﻿using LightCAD.Core;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text;

namespace LightCAD.Runtime
{
    /// <summary>
    /// 对应于DocumentControl+Document的运行时管理类
    /// </summary>
    public class DocumentRuntime : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;
        public LcDocument Document { get; private set; }
        public IDocumentControl DocumentCtrl { get; private set; }
        public ICommandControl CommandCtrl { get; internal set; }

        public DrawingEditRuntime DrawingEditRt { get; internal set; }

        public PropertiesRuntime PropertiesRt { get; internal set; }

        private bool changeNotSaved;
        public bool ChangeNotSaved
        {
            get { return this.changeNotSaved; }
            set
            {
                var changed = (this.changeNotSaved != value);
                this.changeNotSaved = value;
                if (changed) OnPropertyChanged();
            }
        }
        public bool IsActive { get; set; }
        public DocumentAction Action { get; set; }

        public DocumentRuntime(LcDocument document, IDocumentControl documentCtrl)
        {
            this.Document = document;
            this.DocumentCtrl = documentCtrl;
            CommandCenter.Instance.CommandExecute += Instance_CommandExecute;
            this.Action = new DocumentAction(this);
        }

        private void Instance_CommandExecute(object sender, CommandExecuteEventArgs e)
        {
            if (!this.IsActive) return;//非活动不接受命令

            var vportCmds = new string[] { "OPENUCS", "CLOSEUCS", "PLANUCS", "NORMALUCS" };
            if (Array.IndexOf(vportCmds, e.Command.Name.ToUpper()) >= 0)
            {
                this.DrawingEditRt.ActiveViewportRt.CommandExecute(e.Command);
            }

            var fileCmds = new string[] { "OPENFILE", "SAVE", "SAVEAS","CLOSEFILE" };
            if (Array.IndexOf(fileCmds, e.Command.Name.ToUpper()) >= 0)
            {
                ExecuteCommand(e.Command.Name.ToUpper());
            }
        }

        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(name));
        }

        public void Initilize(ICommandControl commandCtrl, IDrawingEditControl drawingEditCtrl, IPropertyControl propertyCtrl, IModelEditControl modelCtrl = null, IModelViewControl[] modelViewCtrls = null)
        {
            this.CommandCtrl = commandCtrl;
            CommandCenter.Instance.BindDocument(this);

            this.DrawingEditRt = new DrawingEditRuntime(this, drawingEditCtrl);
            this.DrawingEditRt.Initilize();

            this.PropertiesRt = new PropertiesRuntime(this, propertyCtrl);
            //this.InitViewports();




            //this.Editor.AttachSizeChanged(this.OnSizeChanged);
            //this.Editor.AttachViewportChanged(this.OnViewportChanged);
            //this.Editor.AttachViewportRender(this.OnViewportRender);
            //this.Editor.AttachPaperSpaceChanged(this.OnPaperSpaceChanged);
            //this.Editor.AttachPaperSpaceRender(this.OnPaperSpaceRender);

            //this.Editor.AttachSpaceChanged(this.OnSpaceChanged);
        }
        private void InitViewports()
        {
            //var vportBounds = Editor.GetViewportBounds();
            //foreach (var item in vportBounds)
            //{
            //    var vport = new Viewport
            //    {
            //        Width = item.Value.Width,
            //        Height = item.Value.Height,
            //        Center = item.Value.Center
            //    };
            //    this.ViewportRts.Add(item.Key, new ViewportRuntime(this, vport));
            //}
        }


        private void OnSizeChanged(Bounds bounds)
        {
            //this.Bounds = bounds;

        }


        private void OnViewportChanged(string name, Bounds bounds)
        {
            //var vpRt = this.ViewportRts[name];
            //vpRt.Viewport.Width = bounds.Width;
            //vpRt.Viewport.Height = bounds.Height;
            //vpRt.Viewport.Center = bounds.Center;
        }

        private void OnViewportRender(string name, SKSurface surface)
        {
            //var vpRt = this.ViewportRts[name];
            //vpRt.OnRender(surface);

            //var canvas = surface.Canvas;
            //using (SKPaint paint = new SKPaint { Color = SKColors.Red, IsStroke = true })
            //{
            //    canvas.DrawLine(0, 0, 100, 100, paint);
            //}
        }
        private void OnPaperSpaceChanged(string name, Bounds bounds)
        {

        }

        private void OnPaperSpaceRender(string name, SKSurface surface)
        {
            var canvas = surface.Canvas;
            canvas.Clear(SKColors.White);
            using (SKPaint paint = new SKPaint { Color = SKColors.Black, IsStroke = true, TextSize = 24 })
            {
                canvas.DrawLine(0, 0, 100, 100, paint);
                canvas.DrawText(name, 100, 100, paint);

            }
        }

        private void OnSpaceChanged(bool isModel, string paperName)
        {

        }

        public void SetActive(bool isActive)
        {
            this.IsActive = isActive;
            this.DrawingEditRt.Control.SetActive(isActive);
        }

        #region Commands

        public void ExecuteCommand(string cmdName)
        {
            switch(cmdName)
            {
                case "OPENFILE":Open();break;
                case "SAVE": Save(); break;
                case "SAVEAS": SaveAs(); break;
                case "CLOSEFILE": CloseFile(); break;

            }
        }


        public void Erase()
        {
            DocumentManager.CurrentRecorder.BeginAction("ERASE");
            if (this.Action.SelectedElements.Count > 0)
            {
                foreach (var element in this.Action.SelectedElements)
                {
                    this.DrawingEditRt.ActiveViewportRt.ActiveElementSet.RemoveElement(element);
                }
            }
            this.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();
        }

        internal void DragCopy(double dragX, double dragY)
        {
            DocumentManager.CurrentRecorder.BeginAction("DRAGCOPY");
            var copyElements = new List<LcElement>();
            foreach (var element in this.Action.SelectedElements)
            {
                var copyEle = element.Clone();
                this.DrawingEditRt.ActiveViewportRt.ActiveElementSet.InsertElement(copyEle);
                copyElements.Add(copyEle);
            }
            foreach (var element in copyElements)
            {
                this.DrawingEditRt.ActiveViewportRt.ActiveElementSet.MoveElement(element, dragX, dragY);
            }
            this.Action.SetSelectsToDragging(false);
            this.Action.ClearSelects();
            this.Action.SelectElements(copyElements);

            this.Action.ResetElementGrips(copyElements);
            DocumentManager.CurrentRecorder.EndAction();

        }

        internal void Drag(double dragX, double dragY)
        {
            DocumentManager.CurrentRecorder.BeginAction("DRAGMOVE");
            foreach (var element in this.Action.SelectedElements)
            {
                this.DrawingEditRt.ActiveViewportRt.ActiveElementSet.MoveElement(element, dragX, dragY);
            }
            this.Action.ResetElementGrips(this.Action.SelectedElements);
            DocumentManager.CurrentRecorder.EndAction();
        }

        public void Copy()
        {
            if (this.Action.SelectedElements.Count == 0) return;
            var elements = new List<LcElement>();
            var box = new Box2d();
            box.SetEmpty();
            foreach (var element in this.Action.SelectedElements)
            {
                box.Union(element.BoundingBox);
                var copyEle = element.Clone();
                elements.Add(copyEle);
            }

            foreach (var element in elements)
            {
                element.Translate(-box.Location.X, -box.Location.Y);
            }

            var dataObject = AppRuntime.UISystem.NewClipboardDataObject();
            var josn = JsonSerializer.Serialize(elements);
            AppRuntime.UISystem.SetClipboardData(dataObject, "LightCAD_Elements", josn);
            AppRuntime.UISystem.SetToClipboard(dataObject);
        }

        internal void Cut()
        {
            if (this.Action.SelectedElements.Count == 0) return;
            Copy();
            DocumentManager.CurrentRecorder.BeginAction("CUT");
            foreach (var element in this.Action.SelectedElements)
            {
                this.DrawingEditRt.ActiveViewportRt.ActiveElementSet.RemoveElement(element);
            }
            this.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();
        }


        internal void Undo()
        {
            //VPort.CancelAll();
            DocumentManager.CurrentRecorder.UndoAction();
        }
        internal void Redo()
        {
            DocumentManager.CurrentRecorder.RedoAction();
        }

        public void New()
        {
            DocumentManager.New();
        }

        public const string DrawingFileName = "drawing.json";
        public async void Open()
        {
            await AppRuntime.ActiveMainUI.OpenDocument();
        }

        public async void Save()
        {
            var doc = DocumentManager.Current;
            DocumentUtils.Save(doc);
        }
        public async void SaveAs()
        {
            var filePath=await AppRuntime.UISystem.SaveFileDialog();
            if (filePath == null) return;
            var doc = DocumentManager.Current;
            DocumentUtils.Save(doc,filePath);
        }
        public void CloseFile()
        {
             AppRuntime.ActiveMainUI.CloseDocument();
        }

        #endregion

    }
}